﻿//----------------------------------------------------------------
// Desc: 
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2009-10-13
//
// Copyright (c) Fuel4D (http://www.fuel4d.com), All rights reserved.
//
//----------------------------------------------------------------
#pragma once


//----------------------------------------------------------------
// 位置信息
//----------------------------------------------------------------
#ifdef WIN32
FINLINE fuPoint& fuPoint::operator = (const POINT& point)
{
    nX = (funit)point.x;
    nY = (funit)point.y;

    return *this;
}
#endif


//----------------------------------------------------------------
// 矩形区域信息
//----------------------------------------------------------------
#ifdef WIN32
FINLINE fuRect& fuRect::operator = (const RECT& _rect)
{
    set(&_rect);

    return *this;
}
#endif
FINLINE fuRect& fuRect::operator *= (const float _right)
{
    uPos.nX  = funit(uPos.nX  * _right);
    uPos.nY  = funit(uPos.nY  * _right);
    uSize.nW = funit(uSize.nW * _right);
    uSize.nH = funit(uSize.nH * _right);
    return *this;
}
FINLINE fuRect& fuRect::operator /= (const float _right)
{
    uPos.nX  = funit(uPos.nX  / _right);
    uPos.nY  = funit(uPos.nY  / _right);
    uSize.nW = funit(uSize.nW / _right);
    uSize.nH = funit(uSize.nH / _right);
    return *this;
}
FINLINE fuRect fuRect::operator + (const fuRect& _right)
{
    fuRect rc;

    rc.uPos.nX  = uPos.nX  + _right.uPos.nX ;
    rc.uPos.nY  = uPos.nY  + _right.uPos.nY ;
    rc.uSize.nW = uSize.nW + _right.uSize.nW;
    rc.uSize.nH = uSize.nH + _right.uSize.nH;

    return rc;
}
FINLINE fuRect& fuRect::operator += (const fuRect& _right)
{
    uPos.nX  += _right.uPos.nX ;
    uPos.nY  += _right.uPos.nY ;
    uSize.nW += _right.uSize.nW;
    uSize.nH += _right.uSize.nH;
    return *this;
}
#ifdef WIN32
FINLINE void fuRect::set(const RECT* rect)
{
    uPos.nX  = (funit)rect->left;
    uPos.nY  = (funit)rect->top;
    uSize.nW = (funit)(rect->right - rect->left + 1);
    uSize.nH = (funit)(rect->bottom - rect->top + 1);
    if (uSize.nW < 0)
        uSize.nW = 0;
    if (uSize.nH < 0)
        uSize.nH = 0;
}
#endif
FINLINE void fuRect::set(funit x, funit y, funit w, funit h)
{
    uPos.nX  = x;
    uPos.nY  = y;
    uSize.nW = w;
    uSize.nH = h;
    if (uSize.nW < 0)
        uSize.nW = 0;
    if (uSize.nH < 0)
        uSize.nH = 0;
}
FINLINE void fuRect::get(funit& x, funit& y, funit& w, funit& h)
{
    x = uPos.nX;
    y = uPos.nY;
    w = uSize.nW;
    h = uSize.nH;
}
FINLINE void fuRect::scale(fuRect* src, float scale)
{
    uPos = src->uPos;
    uSize = src->uSize;

    *this *= scale;
}
FINLINE void fuRect::fill_ninepal(fuRect* nineRect, funit& w1, funit& w2, funit& w3, funit& h1, funit& h2, funit& h3, funit dstx, funit dsty)
{
    nineRect[0].set(0, 0, w1, h1);
    nineRect[1].set(w1, 0, w2, h1);
    nineRect[2].set(w1 + w2, 0, w3, h1);

    nineRect[3].set(0, h1, w1, h2);
    nineRect[4].set(w1, h1, w2, h2);
    nineRect[5].set(w1 + w2, h1, w3, h2);

    nineRect[6].set(0, h1 + h2, w1, h3);
    nineRect[7].set(w1, h1 + h2, w2, h3);
    nineRect[8].set(w1 + w2, h1 + h2, w3, h3);

    nineRect[0].uPos.add(dstx, dsty);
    nineRect[1].uPos.add(dstx, dsty);
    nineRect[2].uPos.add(dstx, dsty);
    nineRect[3].uPos.add(dstx, dsty);
    nineRect[4].uPos.add(dstx, dsty);
    nineRect[5].uPos.add(dstx, dsty);
    nineRect[6].uPos.add(dstx, dsty);
    nineRect[7].uPos.add(dstx, dsty);
    nineRect[8].uPos.add(dstx, dsty);
}
#ifdef WIN32
FINLINE void fuRect::get_gdiplus(RECT* rect)
{
    rect->left = (long)uPos.nX;
    rect->top  = (long)uPos.nY;
    if (uSize.nW > 0)
        rect->right  = (long)(uPos.nX + uSize.nW - 1);
    else
        rect->right  = (long)uPos.nX;
    if (uSize.nH > 0)
        rect->bottom = (long)(uPos.nY + uSize.nH - 1);
    else
        rect->bottom = (long)uPos.nY;
}
FINLINE void fuRect::get_d3d(RECT* rect, int frame)
{
    rect->left = (long)uPos.nX + frame;
    rect->top  = (long)uPos.nY + frame;
    if (uSize.nW > (funit)frame)
        rect->right  = (long)uPos.nX + (long)uSize.nW - frame;
    else
        rect->right  = (long)uPos.nX;
    if (uSize.nH > (funit)frame)
        rect->bottom = (long)uPos.nY + (long)uSize.nH - frame;
    else
        rect->bottom = (long)uPos.nY;
}
FINLINE void fuRect::get_d3d(RECT* rect, int frame, fuRect* interzone)
{
    get_d3d(rect, frame);

    if (rect->left < (long)interzone->uPos.nX)
        rect->left = (long)interzone->uPos.nX;
    if (rect->right > (long)interzone->uPos.nX + (long)interzone->uSize.nW)
        rect->right = (long)interzone->uPos.nX + (long)interzone->uSize.nW;
    if (rect->left > rect->right)
        rect->left = rect->right;

    if (rect->top < (long)interzone->uPos.nY)
        rect->top = (long)interzone->uPos.nY;
    if (rect->bottom > (long)interzone->uPos.nY + (long)interzone->uSize.nH)
        rect->bottom = (long)interzone->uPos.nY + (long)interzone->uSize.nH;
    if (rect->top > rect->bottom)
        rect->top = rect->bottom;
}
#endif
FINLINE void fuRect::cut(fuRect* interzone)
{
    if (is_empty())
        return;
    if (interzone->is_empty())
        return;

    if (uPos.nX < interzone->uPos.nX)
    {
         funit ofx = interzone->uPos.nX - uPos.nX;
         uPos.nX  += ofx;
         uSize.nW -= ofx;
    }
    if (uPos.nY < interzone->uPos.nY)
    {
        funit ofy = interzone->uPos.nY - uPos.nY;
        uPos.nY  += ofy;
        uSize.nH -= ofy;
    }
    if (uPos.nX + uSize.nW > interzone->uPos.nX + interzone->uSize.nW)
    {
        funit ofw = (uPos.nX + uSize.nW) - (interzone->uPos.nX + interzone->uSize.nW);
        uSize.nW -= ofw;
    }
    if (uPos.nY + uSize.nH > interzone->uPos.nY + interzone->uSize.nH)
    {
        funit ofh = (uPos.nY + uSize.nH) - (interzone->uPos.nY + interzone->uSize.nH);
        uSize.nH -= ofh;
    }
}
FINLINE void fuRect::amend(fuRect* interzone)
{
    if (is_empty())
        return;
    if (interzone->is_empty())
        return;

    if (uPos.nX < interzone->uPos.nX)
        uPos.nX = interzone->uPos.nX;

    if (uPos.nY < interzone->uPos.nY)
        uPos.nY = interzone->uPos.nY;

    if (uSize.nW > interzone->uSize.nW)
        uSize.nW = interzone->uSize.nW;
    if (uSize.nW < 0)
        uSize.nW = 0;

    if (uSize.nH > interzone->uSize.nH)
        uSize.nH = interzone->uSize.nH;
    if (uSize.nH < 0)
        uSize.nH = 0;

    if (uPos.nX + uSize.nW > interzone->uPos.nX + interzone->uSize.nW)
        uPos.nX = interzone->uPos.nX + interzone->uSize.nW - uSize.nW;

    if (uPos.nY + uSize.nH > interzone->uPos.nY + interzone->uSize.nH)
        uPos.nY = interzone->uPos.nY + interzone->uSize.nH - uSize.nH;
}
FINLINE void fuRect::unite(fuRect* interzone)
{
    if (interzone->is_empty())
        return;

    funit right  = FUI_Max(Right(), interzone->Right());
    funit bottom = FUI_Max(Bottom(), interzone->Bottom());

    uPos.nX = FUI_Min(uPos.nX, interzone->uPos.nX);
    uPos.nY = FUI_Min(uPos.nY, interzone->uPos.nY);
    uSize.nW = right  - uPos.nX;
    uSize.nH = bottom - uPos.nY;
}
FINLINE bool fuRect::fillbyfather(const fuRect* father, BYTE align, funit sw, funit sh)
{
    uSize.nW = sw;
    uSize.nH = sh;

    switch (align)
    {
    case eUAM_LeftTop:
        uPos.nX = father->uPos.nX, uPos.nY = father->uPos.nY;
        break;
    case eUAM_RightTop:
        uPos.nX = father->uPos.nX + father->uSize.nW - sw, uPos.nY = father->uPos.nY;
        break;
    case eUAM_LeftBottom:
        uPos.nX = father->uPos.nX, uPos.nY = father->uPos.nY + father->uSize.nH - sh;
        break;
    case eUAM_RightBottom:
        uPos.nX = father->uPos.nX + father->uSize.nW - sw, uPos.nY = father->uPos.nY + father->uSize.nH - sh;
        break;
    case eUAM_Middle:
        uPos.nX = father->uPos.nX + (father->uSize.nW - sw) / (funit)2, uPos.nY = father->uPos.nY + (father->uSize.nH - sh) / (funit)2;
        break;
    case eUAM_LeftMiddle:
        uPos.nX = father->uPos.nX, uPos.nY = father->uPos.nY + (father->uSize.nH - sh) / (funit)2;
        break;
    case eUAM_TopMiddle:
        uPos.nX = father->uPos.nX + (father->uSize.nW - sw) / (funit)2, uPos.nY = father->uPos.nY;
        break;
    case eUAM_RightMiddle:
        uPos.nX = father->uPos.nX + father->uSize.nW - sw, uPos.nY = father->uPos.nY + (father->uSize.nH - sh) / (funit)2;
        break;
    case eUAM_BottomMiddle:
        uPos.nX = father->uPos.nX + (father->uSize.nW - sw) / (funit)2, uPos.nY = father->uPos.nY + father->uSize.nH - sh;
        break;
    default:
        assert(false && "无效的对齐模式");
        return false;
    }
    uPos.nX = (funit)(int)uPos.nX;
    uPos.nY = (funit)(int)uPos.nY;
    return true;
}
FINLINE bool fuRect::ptin(funit x, funit y)
{
    if (x < uPos.nX || y < uPos.nY || x > uPos.nX + uSize.nW || y > uPos.nY + uSize.nH)
        return false;
    return true;
}
FINLINE bool fuRect::rectin(fuRect* rc)
{
    return ptin(rc->uPos.nX, rc->uPos.nY) && ptin(rc->uPos.nX + rc->uSize.nW, rc->uPos.nY + rc->uSize.nH);
}
FINLINE bool fuRect::cross(fuRect* rc)
{
    if (ptin(rc->uPos.nX, rc->uPos.nY))
        return true;
    if (ptin(rc->Right(), rc->Bottom()))
        return true;
    if (ptin(rc->Right(), rc->uPos.nY))
        return true;
    if (ptin(rc->uPos.nX, rc->Bottom()))
        return true;

    if (rc->ptin(uPos.nX, uPos.nY))
        return true;
    if (rc->ptin(Right(), Bottom()))
        return true;
    if (rc->ptin(Right(), uPos.nY))
        return true;
    if (rc->ptin(uPos.nX, Bottom()))
        return true;

    return false;
}
FINLINE void fuRect::make_dst_ninepal(fuRect* dstRect, fuRect* srcRect, fuRect* center, fuRect* nineRect)
{
    assert(!center->is_empty());
    assert(center->uPos.nX + center->uSize.nW < srcRect->uSize.nW);
    assert(center->uPos.nY + center->uSize.nH < srcRect->uSize.nH);

    //RECT rCenter;
    //center->get_gdiplus(&rCenter);

    funit w1 = center->uPos.nX;
    funit w3 = srcRect->uSize.nW - (center->uPos.nX + center->uSize.nW) - 1;
    funit w2 = dstRect->uSize.nW - w1 - w3;
    funit h1 = center->uPos.nY;
    funit h3 = srcRect->uSize.nH - (center->uPos.nY + center->uSize.nH) - 1;
    funit h2 = dstRect->uSize.nH - h1 - h3;

    fill_ninepal(nineRect, w1, w2, w3, h1, h2, h3, dstRect->uPos.nX, dstRect->uPos.nY);
}
FINLINE void fuRect::make_src_ninepal(fuRect* srcRect, fuRect* center, fuRect* nineRect)
{
    assert(!center->is_empty());
    assert(center->uPos.nX + center->uSize.nW < srcRect->uSize.nW);
    assert(center->uPos.nY + center->uSize.nH < srcRect->uSize.nH);

    //RECT rCenter;
    //center->get_gdiplus(&rCenter);

    funit w1 = center->uPos.nX;
    funit w3 = srcRect->uSize.nW - (center->uPos.nX + center->uSize.nW) - 1;
    funit w2 = srcRect->uSize.nW - w1 - w3;
    funit h1 = center->uPos.nY;
    funit h3 = srcRect->uSize.nH - (center->uPos.nY + center->uSize.nH) - 1;
    funit h2 = srcRect->uSize.nH - h1 - h3;

    fill_ninepal(nineRect, w1, w2, w3, h1, h2, h3, srcRect->uPos.nX, srcRect->uPos.nY);
}
FINLINE void fuRect::make_dst_threepal(fuRect* dstRect, fuRect* srcRect, fuRect* center, fuRect* threeRect, bool horizontal)
{
    assert(!center->is_empty());

    //RECT rCenter;
    //center->get_gdiplus(&rCenter);

    if (horizontal)
    {
        funit w1 = center->uPos.nX;
        funit w3 = srcRect->uSize.nW - (center->uPos.nX + center->uSize.nW) - 1;
        funit w2 = dstRect->uSize.nW - w1 - w3;
        funit h  = dstRect->uSize.nH;

        if (w2 < 0)
        {
            w2 = 0;
            if (dstRect->uSize.nW > w3)
                w1 = dstRect->uSize.nW - w3;
            else if (dstRect->uSize.nW < w3)
                w1 = 0, w3 = dstRect->uSize.nW;
            else
                w1 = 0;
        }

        threeRect[0].set(0, 0, w1, h);
        threeRect[1].set(w1, 0, w2, h);
        threeRect[2].set(w1 + w2, 0, w3, h);
    }
    else
    {
        funit h1 = center->uPos.nY;
        funit h3 = srcRect->uSize.nH - (center->uPos.nY + center->uSize.nH) - 1;
        funit h2 = dstRect->uSize.nH - h1 - h3;
        funit w  = dstRect->uSize.nW;

        if (h2 < 0)
        {
            h2 = 0;
            if (dstRect->uSize.nH > h3)
                h1 = dstRect->uSize.nH - h3;
            else if (dstRect->uSize.nH < h3)
                h1 = 0, h3 = dstRect->uSize.nH;
            else
                h1 = 0;
        }

        threeRect[0].set(0, 0, w, h1);
        threeRect[1].set(0, h1, w, h2);
        threeRect[2].set(0, h1 + h2, w, h3);
    }

    threeRect[0].uPos.add(dstRect->uPos.nX, dstRect->uPos.nY);
    threeRect[1].uPos.add(dstRect->uPos.nX, dstRect->uPos.nY);
    threeRect[2].uPos.add(dstRect->uPos.nX, dstRect->uPos.nY);
}
FINLINE void fuRect::make_src_threepal(fuRect* srcRect, fuRect* center, fuRect* threeRect, bool horizontal)
{
    assert(!center->is_empty());

    //RECT rCenter;
    //center->get_gdiplus(&rCenter);

    if (horizontal)
    {
        funit w1 = center->uPos.nX;
        funit w3 = srcRect->uSize.nW - (center->uPos.nX + center->uSize.nW) - 1;
        funit w2 = srcRect->uSize.nW - w1 - w3;
        funit h  = srcRect->uSize.nH;

        threeRect[0].set(0, 0, w1, h);
        threeRect[1].set(w1, 0, w2, h);
        threeRect[2].set(w1 + w2, 0, w3, h);
    }
    else
    {
        funit h1 = center->uPos.nY;
        funit h3 = srcRect->uSize.nH - (center->uPos.nY + center->uSize.nH) - 1;
        funit h2 = srcRect->uSize.nH - h1 - h3;
        funit w  = srcRect->uSize.nW;

        threeRect[0].set(0, 0, w, h1);
        threeRect[1].set(0, h1, w, h2);
        threeRect[2].set(0, h1 + h2, w, h3);
    }

    threeRect[0].uPos.add(srcRect->uPos.nX, srcRect->uPos.nY);
    threeRect[1].uPos.add(srcRect->uPos.nX, srcRect->uPos.nY);
    threeRect[2].uPos.add(srcRect->uPos.nX, srcRect->uPos.nY);
}

FINLINE void fuRect::split_w(fuRect* dst_left, fuRect* dst_right, funit left_w)
{
    *dst_left = *this;
    *dst_right = *this;
    dst_left->uSize.nW = left_w;
    dst_right->uPos.nX += left_w;
    dst_right->uSize.nW -= left_w;
}

FINLINE void fuRect::split_h(fuRect* dst_up, fuRect* dst_down, funit up_h)
{
}